package com.frame.project.service.system.dept.imp;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.frame.common.constant.UserConstants;
import com.frame.common.exception.ServiceException;
import com.frame.common.utils.StringUtils;
import com.frame.common.utils.security.ShiroUtils;
import com.frame.common.utils.spring.SpringUtils;
import com.frame.framework.aspectj.DataScopeAspect;
import com.frame.framework.aspectj.lang.annotation.DataScope;
import com.frame.framework.web.domain.Ztree;
import com.frame.framework.web.error.WebError;
import com.frame.framework.web.service.imp.AbstractBaseService;
import com.frame.project.domain.system.dept.Dept;
import com.frame.project.domain.system.role.Role;
import com.frame.project.domain.system.user.User;
import com.frame.project.repository.system.dept.DeptRepository;
import com.frame.project.repository.system.user.UserRepository;
import com.frame.project.service.system.dept.DeptService;

/**
 * 
 * @className ：DeptServiceImpl
 * @describe ：部门
 */
@Service
public class DeptServiceImpl extends AbstractBaseService<Dept> implements DeptService {

	@Autowired
	private DeptRepository deptRepository;
	
	@Autowired
	private UserRepository userRepository;
	
	@PersistenceContext
    private EntityManager em;
	
	/**
     * 查询部门管理数据
     * 
     * @param dept 部门信息
     * @return 部门信息集合
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<Dept> selectDeptList(Dept dept)
    {
    	 StringBuilder sql = new StringBuilder(
                 "select d.id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.remove_status, d.create_by, d.create_time from sys_dept d" +
                         " where d.remove_status = 0");

         if(dept.getId() != null){
             sql.append(" and d.id = ").append(dept.getId());
         }

         if(dept.getParentId() != null){
             sql.append(" and d.parent_id = ").append(dept.getParentId());
         }

         if(StringUtils.isNotBlank(dept.getDeptName())){
             sql.append(" and d.dept_name like concat('%','").append(dept.getDeptName()).append("', '%')");
         }

         if(StringUtils.isNotBlank(dept.getStatus())){
             sql.append(" and d.status = '").append(dept.getStatus()).append("'");
         }

         if(dept.getParams() != null){
             Map<String, Object> params = dept.getParams();
             String sqlString = (String)params.get(DataScopeAspect.DATA_SCOPE);
             if(StringUtils.isNotBlank(sqlString)){
                 sql.append(sqlString);
             }
         }

         sql.append(" order by d.parent_id, d.order_num");
         Query query = em.createNativeQuery(sql.toString());
         List<Object[]> list = query.getResultList();
         List<Dept> deptList = new ArrayList<Dept>();
         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        for(Object[] objects : list){
        	Dept d = new Dept();
            d.setId(Long.parseLong(objects[0].toString()));
            d.setParentId(Long.parseLong(objects[1].toString()));
            d.setAncestors(objects[2].toString());
            d.setDeptName(objects[3].toString());
            d.setOrderNum(Integer.parseInt(objects[4].toString()));
            d.setLeader(objects[5].toString());
            d.setPhone(objects[6].toString());
            d.setEmail(objects[7].toString());
            d.setStatus(objects[8].toString());
            d.setRemoveStatus(Integer.parseInt(objects[9].toString()));
            d.setCreateBy(objects[10].toString());
            try {
                d.setCreateTime(format.parse(objects[11].toString()));
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            deptList.add(d);
        }

         return deptList;
    }
    
    /**
     * 查询部门管理树
     * 
     * @param dept 部门信息
     * @return 所有部门信息
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<Ztree> selectDeptTree(Dept dept)
    {
        List<Dept> deptList = selectDeptList(dept);
        List<Ztree> ztrees = initZtree(deptList);
        return ztrees;
    }
    
    /**
     * 根据角色ID查询部门（数据权限）
     *
     * @param role 角色对象
     * @return 部门列表（数据权限）
     */
    @Override
    public List<Ztree> roleDeptTreeData(Role role)
    {
        Long roleId = role.getId();
        List<Ztree> ztrees = new ArrayList<Ztree>();
        List<Dept> deptList = selectDeptList(new Dept());
        if (StringUtils.isNotNull(roleId))
        {
            List<String> roleDeptList = deptRepository.selectRoleDeptTree(roleId);
            ztrees = initZtree(deptList, roleDeptList);
        }
        else
        {
            ztrees = initZtree(deptList);
        }
        return ztrees;
    }
    
    /**
     * 对象转部门树
     *
     * @param deptList 部门列表
     * @return 树结构列表
     */
    public List<Ztree> initZtree(List<Dept> deptList)
    {
        return initZtree(deptList, null);
    }
    
    /**
     * 对象转部门树
     *
     * @param deptList 部门列表
     * @param roleDeptList 角色已存在菜单列表
     * @return 树结构列表
     */
    public List<Ztree> initZtree(List<Dept> deptList, List<String> roleDeptList)
    {
        List<Ztree> ztrees = new ArrayList<Ztree>();
        boolean isCheck = StringUtils.isNotNull(roleDeptList);
        for (Dept dept : deptList)
        {
            if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()))
            {
                Ztree ztree = new Ztree();
                ztree.setId(dept.getId());
                ztree.setpId(dept.getParentId());
                ztree.setName(dept.getDeptName());
                ztree.setTitle(dept.getDeptName());
                if (isCheck)
                {
                    ztree.setChecked(roleDeptList.contains(dept.getId() + dept.getDeptName()));
                }
                ztrees.add(ztree);
            }
        }
        return ztrees;
    }
    
    /**
     * 查询部门人数
     * 
     * @param parentId 部门ID
     * @return 结果
     */
    @Override
    public Integer selectDeptCountByParent(Long parentId)
    {
        return deptRepository.selectDeptCountByParent(parentId);
    }
    
    /**
     * 查询部门是否存在用户
     * 
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkDeptExistUser(Long deptId)
    {
        int result = userRepository.checkDeptExistUser(deptId);
        return result > 0 ? true : false;
    }
    
    /**
     * 新增保存部门信息
     * 
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public WebError insertDept(Dept dept)
    {
        Dept sup = findById(dept.getParentId());
        // 如果父节点不为"正常"状态,则不允许新增子节点
        if (!UserConstants.DEPT_NORMAL.equals(sup.getStatus()))
        {
            return new WebError(-1, "上级部门(" + sup.getDeptName() + ")已停用，不允许新增");
        }
        dept.setAncestors(sup.getAncestors() + "," + dept.getParentId());
        dept.setSupDept(sup);
        add(dept);
        
        return new WebError();
    }
    
    /**
     * 修改保存部门信息
     * 
     * @param dept 部门信息
     */
    @Override
    @Transactional
    public void updateDept(Dept dept)
    {
    	//新父类
        Dept newParentDept = findById(dept.getParentId());
        Dept oldDept = findById(dept.getId());
        if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept))
        {
            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getId();
            String oldAncestors = oldDept.getAncestors();
            
            oldDept.setSupDept(newParentDept);
            oldDept.setParentId(dept.getParentId());
            oldDept.setAncestors(newAncestors);
            updateDeptChildren(oldDept.getId(), newAncestors, oldAncestors);
        }
        oldDept.setDeptName(dept.getDeptName());
        oldDept.setOrderNum(dept.getOrderNum());
        oldDept.setLeader(dept.getLeader());
        oldDept.setPhone(dept.getPhone());
        oldDept.setEmail(dept.getEmail());
        oldDept.setStatus(dept.getStatus());
        modify(oldDept);
        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()))
        {
            // 如果该部门是启用状态，则启用该部门的所有上级部门
            updateParentDeptStatus(dept);
        }
    }
    
    /**
     * 修改该部门的父级部门状态
     * 
     * @param dept 当前部门
     */
    private void updateParentDeptStatus(Dept dept)
    {
    	
    	if(dept.getParentId() == 0L) {
    		
    	}else {
    		Dept sup = findById(dept.getParentId());
    		sup.setStatus(UserConstants.DEPT_NORMAL);
            modify(sup);
            updateParentDeptStatus(sup);
    	}
    	
    }
    
    /**
     * 修改子元素关系
     * 
     * @param deptId 被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors)
    {
        List<Dept> children = deptRepository.selectChildrenDeptById(deptId);
        for (Dept child : children)
        {
            child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors));
            modify(child);
        }
    }
    
    /**
     * 修改子元素关系
     * 
     * @param deptId 部门ID
     * @param ancestors 元素列表
     */
    public void updateDeptChildren(Long deptId, String ancestors)
    {
        Dept dept = new Dept();
        Dept parent = findById(deptId);
        dept.setSupDept(parent);
        List<Dept> childrens = selectDeptList(dept);
        for (Dept children : childrens)
        {
            children.setAncestors(ancestors + "," + dept.getSupDept().getId());
            modify(children);
        }
    }
    
    /**
     * 根据ID查询所有子部门（正常状态）
     * 
     * @param deptId 部门ID
     * @return 子部门数
     */
    @Override
    public Integer selectNormalChildrenDeptById(Long deptId)
    {
        return deptRepository.selectNormalChildrenDeptById(deptId);
    }
    
    /**
     * 校验部门名称是否唯一
     * 
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public String checkDeptNameUnique(Dept dept)
    {
        Long deptId = StringUtils.isNull(dept.getId()) ? -1L : dept.getId();
        Dept info = deptRepository.findByDeptNameAndParentId(dept.getDeptName(), dept.getParentId());
        if (StringUtils.isNotNull(info) && info.getId() != deptId)
        {
            return UserConstants.DEPT_NAME_NOT_UNIQUE;
        }
        return UserConstants.DEPT_NAME_UNIQUE;
    }
    
    @Override
    public Dept findByParentId(Long parentId){
    	return deptRepository.findByParentId(parentId);
    }

    /**
     * 校验部门是否有数据权限
     * 
     * @param deptId 部门id
     */
	@Override
	public void checkDeptDataScope(Long deptId) {
		Optional<User> op = userRepository.findById(ShiroUtils.getUserId());
		User u = op.get();
		if (!User.isAdmin(u.getLoginName()))
        {
            Dept dept = new Dept();
            dept.setId(deptId);
            List<Dept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
            if (StringUtils.isEmpty(depts))
            {
                throw new ServiceException("没有权限访问部门数据！");
            }
        }
		
	}
}
